﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Media;
using Db4objects.Db4o;
using Db4objects.Db4o.Config;
using Db4objects.Db4o.Linq;
using Db4objects.Db4o.Query;
using Northwind.Config;
using Northwind.Objects;

namespace Northwind.Management
{
    /// <summary>
    /// Interaction logic for UserControl_Order.xaml
    /// </summary>
    public partial class UserControl_Order : UserControl
    {
        #region Data
        private OrderViewModeEnum _OrderViewModeEnum;
        private Northwind.Objects.Customer selectedCustomer = null;
        private Northwind.Objects.Order _OrderEditing;
        private string DateFormat = "yyyyMMddHHmmss";
        #endregion

        public UserControl_Order()
        {
            InitializeComponent();
            this.Loaded += UserControl_Order_Loaded;
        }

        #region Private Methods
        private void UserControl_Order_Loaded(object sender, RoutedEventArgs e)
        {
            InitData();

            if (_OrderViewModeEnum == OrderViewModeEnum.New)
            {
                _OrderEditing = new Northwind.Objects.Order();
                _OrderEditing.OrderNo = DateTime.Now.ToString(DateFormat);
                _OrderEditing.SaleDate = DateTime.Now;
                _OrderEditing.Employee = SharedData.CurrentUser;

                GroupBox_Sale.DataContext = _OrderEditing;
            }
        }

        private void InitData()
        {
            #region Use DB4O
            using (IObjectContainer db = Db4oEmbedded.OpenFile(DataBaseConfig.DBFileName))
            {
                #region Get all Customers
                List<Northwind.Objects.Customer> customers = new List<Objects.Customer>();

                #region Use QBE

                //Northwind.Objects.Customer customerProto = new Northwind.Objects.Customer();
                //customerProto.CompanyName = "Microsoft";
                //IObjectSet results = db.QueryByExample(customerProto);

                #endregion

                #region Use NQ

                //IList<Northwind.Objects.Customer> results = db.Query<Northwind.Objects.Customer>(delegate(Northwind.Objects.Customer customer)
                //{
                //    return true;
                //});

                //IList<Northwind.Objects.Customer> results = db.Query<Northwind.Objects.Customer>(
                //(customer) =>
                //{
                //    return customer.CompanyName == "Microsoft";
                //});

                #endregion

                #region Use LINQ

                //IEnumerable<Northwind.Objects.Customer> results = from Northwind.Objects.Customer c in db
                //                                                  where c.CompanyName == "Microsoft"
                //                                                  select c;

                #endregion

                #region SODA

                IQuery query = db.Query();
                query.Constrain(typeof(Northwind.Objects.Customer));
                //query.Descend("CompanyName").Constrain("Microsoft");
                IObjectSet results = query.Execute();

                #endregion

                foreach (object item in results)
                {
                    customers.Add((Northwind.Objects.Customer)item);
                }
                ComboBox_CompanyName.ItemsSource = customers;
                ComboBox_ContactName.ItemsSource = customers;
                #endregion

                #region Get all Products
                List<Northwind.Objects.Product> products = new List<Objects.Product>();
                Northwind.Objects.Product productProto = new Northwind.Objects.Product();
                IObjectSet resultsProduct = db.QueryByExample(productProto);

                foreach (object item in resultsProduct)
                {
                    products.Add((Northwind.Objects.Product)item);
                }
                ComboBox_Products.ItemsSource = products;
                #endregion
            }
            #endregion

            #region Use SQL
            //using (NorthwindDataContext adapter = new NorthwindDataContext())
            //{
            //    Northwind.Import.Data.Customer[] customer = adapter.Customers.ToArray();
            //    ComboBox_CompanyName.ItemsSource = customer;
            //    ComboBox_ContactName.ItemsSource = customer;

            //    Northwind.Import.Data.Product[] products = adapter.Products.ToArray();
            //    ComboBox_Products.ItemsSource = products;
            //}
            #endregion
        }

        private void RefreshListOrderDetails()
        {
            ListView_OrderDetails.ItemsSource = null;
            ListView_OrderDetails.ItemsSource = _OrderEditing.OrderDetails;
            TextBox_TotalBillMoney.Text = CurrencyConverter.GetCurrency(_OrderEditing.TotalMoney);
        }
        #endregion

        #region Public Methods
        public void SetParamaters(OrderViewModeEnum viewMode)
        {
            _OrderViewModeEnum = viewMode;
        }
        #endregion

        #region Events
        private void Button_Exit_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("Sorry this function has not been implemented yet.");
        }

        private void ComboBox_CompanyName_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
        {
            if (ComboBox_CompanyName.SelectedItem != null)
            {
                selectedCustomer = (Northwind.Objects.Customer)ComboBox_CompanyName.SelectedItem;
                GroupBox_Customer.DataContext = selectedCustomer;
            }
        }

        private void ComboBox_ContactName_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
        {
            if (ComboBox_ContactName.SelectedItem != null)
            {
                selectedCustomer = (Northwind.Objects.Customer)ComboBox_ContactName.SelectedItem;
                GroupBox_Customer.DataContext = selectedCustomer;
            }
        }

        private void Buton_AddNew_Click_1(object sender, RoutedEventArgs e)
        {
            if (ComboBox_Products.SelectedItem != null)
            {
                Northwind.Objects.Product selectedProduct = (Northwind.Objects.Product)ComboBox_Products.SelectedItem;

                OrderDetail orderDetail = new OrderDetail();
                orderDetail.Order = _OrderEditing;
                orderDetail.Product = selectedProduct;
                orderDetail.UnitPrice = (decimal)selectedProduct.UnitPrice;
                if (!string.IsNullOrEmpty(TextBox_Quantity.Text))
                {
                    int iTemp;
                    if (int.TryParse(TextBox_Quantity.Text, out iTemp))
                    {
                        orderDetail.Quantity = iTemp;
                    }
                }
                orderDetail.TotalPrice = orderDetail.UnitPrice * orderDetail.Quantity;

                _OrderEditing.ProductCount = _OrderEditing.ProductCount == null ? 1 : _OrderEditing.ProductCount + 1;
                orderDetail.SequenceOrder = _OrderEditing.ProductCount.Value;
                _OrderEditing.OrderDetails.Add(orderDetail);
                _OrderEditing.TotalMoney = _OrderEditing.OrderDetails.Sum(od => od.TotalPrice);

                RefreshListOrderDetails();
            }
            else
            {
                MessageBox.Show("Please choose any products first.", "Order", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
            }
        }

        private void Button_Remove_Click(object sender, RoutedEventArgs e)
        {
            ListViewItem lvi = GetAncestorByType(e.OriginalSource as DependencyObject, typeof(ListViewItem)) as ListViewItem;

            if (lvi != null)
            {
                ListView_OrderDetails.SelectedIndex = ListView_OrderDetails.ItemContainerGenerator.IndexFromContainer(lvi);
                Northwind.Objects.OrderDetail selectedOrderDetail = ((Northwind.Objects.OrderDetail)ListView_OrderDetails.SelectedItem);
                if (selectedOrderDetail != null)
                {
                    MessageBoxResult result = MessageBox.Show(string.Format("Are you sure you want to remove the product [{0}] ?", selectedOrderDetail.Product.ProductName), "Order", MessageBoxButton.YesNo, MessageBoxImage.Question, MessageBoxResult.No);
                    if (result == MessageBoxResult.Yes)
                    {
                        _OrderEditing.OrderDetails.Remove(selectedOrderDetail);
                        RefreshListOrderDetails();
                    }
                }
            }
        }

        private void Button_Save_Click_1(object sender, RoutedEventArgs e)
        {
            try
            {
                _OrderEditing.Customer = selectedCustomer;

                IEmbeddedConfiguration config = Db4oEmbedded.NewConfiguration();
                config.Common.ObjectClass(typeof(Northwind.Objects.Order)).CascadeOnUpdate(true);
                using (IObjectContainer db = Db4oEmbedded.OpenFile(config, DataBaseConfig.DBFileName))
                {
                    db.Store(_OrderEditing);
                }

                MessageBox.Show("Save success!", "Order", MessageBoxButton.OK, MessageBoxImage.Information, MessageBoxResult.OK);
                RefreshOrder();
            }
            catch
            {
                MessageBox.Show("Save failed!", "Order", MessageBoxButton.OK, MessageBoxImage.Error, MessageBoxResult.OK);
            }
        }

        private void RefreshOrder()
        {
            _OrderEditing = new Order();
            DockPanel_Order.DataContext = null;
            DockPanel_Order.DataContext = _OrderEditing;
            GroupBox_Sale.DataContext = null;
            GroupBox_Customer.DataContext = null;
            ListView_OrderDetails.ItemsSource = null;
        }

        private void Button_Discard_Click(object sender, RoutedEventArgs e)
        {
            RefreshOrder();
        }

        #endregion

        #region Ultilities
        public static DependencyObject GetAncestorByType(DependencyObject element, Type type)
        {
            if (element == null) return null;
            if (element.GetType() == type) return element;
            return GetAncestorByType(VisualTreeHelper.GetParent(element), type);
        }
        #endregion
    }

    public class CurrencyConverter : IValueConverter
    {
        #region IValueConverter Members

        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return GetCurrency(value);
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return null;
        }

        public static string GetCurrency(object value)
        {
            if (value != null)
                return string.Format(new System.Globalization.CultureInfo("en-US"), "{0:C}", value);
            return string.Empty;
        }

        #endregion
    }
}
